/*
 * Ext JS Library 2.0 RC 1
 * Copyright(c) 2006-2007, Ext JS, LLC.
 * licensing@extjs.com
 * 
 * http://extjs.com/license
 */

Ext.ux.Portal = Ext.extend(Ext.Panel, {
	layout : 'column',
	autoScroll : true,
	cls : 'x-portal',
	defaultType : 'portalcolumn',

	initComponent : function() {
		Ext.ux.Portal.superclass.initComponent.call(this);
		this.addEvents( {
			validatedrop : true,
			beforedragover : true,
			dragover : true,
			beforedrop : true,
			drop : true
		});
	},

	initEvents : function() {
		Ext.ux.Portal.superclass.initEvents.call(this);
		this.dd = new Ext.ux.Portal.DropZone(this, this.dropConfig);
	}
});
Ext.reg('portal', Ext.ux.Portal);

Ext.ux.Portal.DropZone = function(portal, cfg) {
	this.portal = portal;
	Ext.dd.ScrollManager.register(portal.body);
	Ext.ux.Portal.DropZone.superclass.constructor.call(this, portal.bwrap.dom,
			cfg);
	portal.body.ddScrollConfig = this.ddScrollConfig;
};

Ext
		.extend(
				Ext.ux.Portal.DropZone,
				Ext.dd.DropTarget,
				{
					ddScrollConfig : {
						vthresh : 50,
						hthresh : -1,
						animate : true,
						increment : 200
					},

					createEvent : function(dd, e, data, col, c, pos) {
						return {
							portal : this.portal,
							panel : data.panel,
							columnIndex : col,
							column : c,
							position : pos,
							data : data,
							source : dd,
							rawEvent : e,
							status : this.dropAllowed
						};
					},

					notifyOver : function(dd, e, data) {
						var xy = e.getXY(), portal = this.portal, px = dd.proxy;

						// case column widths
						if (!this.grid) {
							this.grid = this.getGrid();
						}

						// handle case scroll where scrollbars appear during drag
						var cw = portal.body.dom.clientWidth;
						if (!this.lastCW) {
							this.lastCW = cw;
						} else if (this.lastCW != cw) {
							this.lastCW = cw;
							portal.doLayout();
							this.grid = this.getGrid();
						}

						// determine column
						var col = 0, xs = this.grid.columnX, cmatch = false;
						for ( var len = xs.length; col < len; col++) {
							if (xy[0] < (xs[col].x + xs[col].w)) {
								cmatch = true;
								break;
							}
						}
						// no match, fix last index
						if (!cmatch) {
							col--;
						}

						// find insert position
						var p, match = false, pos = 0, c = portal.items
								.itemAt(col), items = c.items.items;

						for ( var len = items.length; pos < len; pos++) {
							p = items[pos];
							var h = p.el.getHeight();
							if (h !== 0 && (p.el.getY() + (h / 2)) > xy[1]) {
								match = true;
								break;
							}
						}

						var overEvent = this.createEvent(dd, e, data, col, c,
								match && p ? pos : c.items.getCount());

						if (portal.fireEvent('validatedrop', overEvent) !== false
								&& portal
										.fireEvent('beforedragover', overEvent) !== false) {

							// make sure proxy width is fluid
							px.getProxy().setWidth('auto');

							if (p) {
								px.moveProxy(p.el.dom.parentNode,
										match ? p.el.dom : null);
							} else {
								px.moveProxy(c.el.dom, null);
							}

							this.lastPos = {
								c : c,
								col : col,
								p : match && p ? pos : false
							};
							this.scrollPos = portal.body.getScroll();

							portal.fireEvent('dragover', overEvent);

							return overEvent.status;
							;
						} else {
							return overEvent.status;
						}

					},

					notifyOut : function() {
						delete this.grid;
					},

					notifyDrop : function(dd, e, data) {
						delete this.grid;
						if (!this.lastPos) {
							return;
						}
						var c = this.lastPos.c, col = this.lastPos.col, pos = this.lastPos.p;

						var dropEvent = this.createEvent(dd, e, data, col, c,
								pos !== false ? pos : c.items.getCount());

						if (this.portal.fireEvent('validatedrop', dropEvent) !== false
								&& this.portal.fireEvent('beforedrop',
										dropEvent) !== false) {

							dd.proxy.getProxy().remove();
							dd.panel.el.dom.parentNode
									.removeChild(dd.panel.el.dom);
							if (pos !== false) {
								c.insert(pos, dd.panel);
							} else {
								c.add(dd.panel);
							}

							c.doLayout();

							this.portal.fireEvent('drop', dropEvent);

							// scroll position is lost on drop, fix it
							var st = this.scrollPos.top;
							if (st) {
								var d = this.portal.body.dom;
								setTimeout(function() {
									d.scrollTop = st;
								}, 10);
							}

						}
						delete this.lastPos;
					},

					// internal cache of body and column coords
					getGrid : function() {
						var box = this.portal.bwrap.getBox();
						box.columnX = [];
						this.portal.items.each(function(c) {
							box.columnX.push( {
								x : c.el.getX(),
								w : c.el.getWidth()
							});
						});
						return box;
					}
				});

/*
 * Ext JS Library 2.0 RC 1
 * Copyright(c) 2006-2007, Ext JS, LLC.
 * licensing@extjs.com
 * 
 * http://extjs.com/license
 */

Ext.ux.PortalColumn = Ext.extend(Ext.Container, {
	layout : 'anchor',
	autoEl : 'div',
	defaultType : 'portlet',
	cls : 'x-portal-column'
});
Ext.reg('portalcolumn', Ext.ux.PortalColumn);

/*
 * Ext JS Library 2.0 RC 1
 * Copyright(c) 2006-2007, Ext JS, LLC.
 * licensing@extjs.com
 * 
 * http://extjs.com/license
 */

Ext.ux.Portlet = Ext.extend(Ext.Panel, {
	anchor : '100%',
	frame : true,
	collapsible : true,
	draggable : true,
	cls : 'x-portlet'
});
Ext.reg('portlet', Ext.ux.Portlet);
